/*---------------------------------------------------------------------------*/
/*
	Risse [りせ]
	 stands for "Risse Is a Sweet Script Engine"
	Copyright (C) 2000 W.Dee <dee@kikyou.info> and contributors

	See details of license at "license.txt"
*/
//---------------------------------------------------------------------------
//! @file
//! @brief マルチスレッド関連ユーティリティ
//---------------------------------------------------------------------------
#ifdef RISSE_SUPPORT_THREADS

#include "prec.h"
#include "risseThread.h"

#include <wx/utils.h>

namespace Risse 
{
RISSE_DEFINE_SOURCE_ID(24795,6838,687,16805,21894,40786,6545,48673);

//---------------------------------------------------------------------------
/**
 * tThread の内部的な実装
 */
class tThreadInternal : public wxThread
{
	tThread * Owner;
public:
	tThreadInternal(tThread * owner);
	~tThreadInternal(); // virtual

private:
	ExitCode Entry();
};
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
/**
 * コンストラクタ
 */
tThreadInternal::tThreadInternal(tThread * owner) :
	wxThread(wxTHREAD_DETACHED)
{
	// フィールドの初期化
	Owner = owner;

	// スレッドを作成する
	Create();
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
/**
 * デストラクタ
 */
tThreadInternal::~tThreadInternal()
{
	// ミューテックスのロックを解除する
	Owner->Internal = NULL; // 自分自身への参照を消す
	Owner->ThreadMutex.Unlock();
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
/**
 * スレッドのエントリポイント
 */
wxThread::ExitCode tThreadInternal::Entry()
{
	// ミューテックスをロックする
	Owner->ThreadMutex.Lock();

	// スレッドが実際に開始したことを表す
	++Owner->Started;

	// スレッドのメイン関数を実行する
	// 例外が発生するかも。
	Owner->CallExecute();


	return 0;
}
//---------------------------------------------------------------------------









//---------------------------------------------------------------------------
tThread::tThread() : StartInitiated(0), Started(0), _Terminated(0)
{
	Internal = new tThreadInternal(this);
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
tThread::~tThread()
{
	//注意	このデストラクタはメインスレッド以外から非同期に呼ばれる可能性がある
	if((long)Started || (long)StartInitiated) Wait();

	// Internal は自分で自分自身を解放するのでここでは解放しない
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
void tThread::Run()
{
	if(++StartInitiated >= 2)
	{
		// StartInitiated が 2以上になったと言うことは
		// すでにスレッドが開始されていると言うこと
		--StartInitiated; // 一応もどしておく
		return;
	}
	Internal->Run();
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
void tThread::Wait()
{
	// まだスレッドが開始していない場合は開始するまで待つ
	while((long)Started == 0) { ::wxMilliSleep(1); } // あまりよい実装とは言えないが……

	// 終了指示
	Terminate();

	// スレッドが終了するまで待つ
	wxMutexLocker lock(ThreadMutex);
}
//---------------------------------------------------------------------------


//---------------------------------------------------------------------------
volatile bool tThread::ShouldTerminate()
{
	return Get_Terminated() || Internal->TestDestroy();
}
//---------------------------------------------------------------------------


} // namespace Risse

#endif
